package com.istock.union.user.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.istock.base.cache.BaseCacheManager;
import com.istock.base.cache.DeleteCache;
import com.istock.base.cache.UseCache;
import com.istock.base.common.api.model.PageInfo;
import com.istock.base.enumration.BaseEnum;
import com.istock.base.mybatis.utils.MybatisFieldConvertUtils;
import com.istock.union.user.client.SSOClientUtils;
import com.istock.union.user.dao.DictDataInfoMapper;
import com.istock.union.user.dao.DictTypeInfoMapper;
import com.istock.union.user.model.DictDataInfo;
import com.istock.union.user.model.DictDataInfoExample;
import com.istock.union.user.model.DictTypeData;
import com.istock.union.user.model.DictTypeInfo;
import com.istock.union.user.model.DictTypeInfoExample;
import com.istock.union.user.model.DictTypeQuery;
import com.istock.union.user.service.DictInfoService;

@Repository
public class DictInfoServiceImpl implements DictInfoService{

	@Autowired
	private DictTypeInfoMapper dictTypeMapper;
	
	@Autowired
	private DictDataInfoMapper dictDataMapper;
	
	@Autowired
	private BaseCacheManager cacheManger;
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	/**页面上的查询
	 * @param typeQuery 页面上可以设置的查询条件
	 * @param page
	 * @return
	 */
	public List<DictTypeInfo> findTypeList(DictTypeQuery typeQuery , PageInfo<DictTypeInfo> page){
		DictTypeInfoExample example = new DictTypeInfoExample();
		DictTypeInfoExample.Criteria criteria = example.createCriteria();
		
		if(typeQuery != null) {
			if(StringUtils.isNotBlank(typeQuery.getDictType())) {
				criteria.andDictTypeLike("%"+typeQuery.getDictType()+"%");
			}
			
			if(StringUtils.isNotBlank(typeQuery.getDictName())) {
				criteria.andDictNameLike("%"+typeQuery.getDictName()+"%");
			}
			
			if(StringUtils.isNotBlank(typeQuery.getBeginTime())) {
				try {
					Date beginTime = DateUtils.parseDate(typeQuery.getBeginTime(), "yyyy-MM-dd" , "yyyy-MM-dd HH:mm:ss");
					criteria.andCreateTimeGreaterThanOrEqualTo(beginTime);
				}catch(Exception e) {
					logger.error("the begin time ["+typeQuery.getBeginTime()+"] can't be parsed to date");
				}
			}
			
			if(StringUtils.isNotBlank(typeQuery.getEndTime())) {
				try {
					Date endTime = DateUtils.parseDate(typeQuery.getEndTime(),  "yyyy-MM-dd" , "yyyy-MM-dd HH:mm:ss");
					criteria.andCreateTimeLessThanOrEqualTo(endTime);
				}catch(Exception e) {
					logger.error("the end time ["+typeQuery.getEndTime()+"] can't be parsed to date");
				}
			}
			
			if(typeQuery.getStatus() != null && typeQuery.getStatus()>0) {
				criteria.andStatusEqualTo(typeQuery.getStatus());
			}
			
			if(StringUtils.isNotBlank(typeQuery.getOrderByColumn())) {
				example.setOrderByClause(MybatisFieldConvertUtils.getInstance().unmarshal("com.istock.union.user.dao.DictTypeInfoMapper", "BaseResultMap", typeQuery.getOrderByColumn())+" "+typeQuery.getIsAsc());
			}
		}
		if(StringUtils.isBlank(example.getOrderByClause())) {
			example.setOrderByClause("ID DESC");
		}
		return dictTypeMapper.selectByExample(example, page);
	}
	
	/**得到某一个数据type下的所有的字典项
	 * @param type 字典类型
	 * @return
	 */
	@UseCache(key="'DICT_'+#type" , expireTime=60*60*24)
	public List<BaseEnum> getEnumsByType(String type) {
		DictDataInfoExample example = new DictDataInfoExample();
		DictDataInfoExample.Criteria criteria = example.createCriteria();
		criteria.andDictTypeEqualTo(type);
		example.setOrderByClause("DICT_SORT ASC");
		List<DictDataInfo> dataList = dictDataMapper.selectByExample(example);
		if(dataList != null){
			List<BaseEnum> result = new ArrayList<BaseEnum>();
			for(DictDataInfo data : dataList){
				result.add(new BaseEnum(data.getDictValue() , data.getDictType() ,data.getDictCode() , data.getCssClass(), data.getDictLabel()));
			}
			return result;
		}
		return null;
	}
	
	
	/**页面编辑某一个数据字典,先得到整个数据字典的所有信息,包含所有的字典项
	 * 如果找不到id,则返回null
	 * @param id
	 * @return
	 */
	public DictTypeData findTypeById(String id) {
		DictTypeInfo info = dictTypeMapper.selectByPrimaryKey(id);
		if(info != null) {
			DictTypeData result = new DictTypeData();
			BeanUtils.copyProperties(info, result);
			
			DictDataInfoExample example = new DictDataInfoExample();
			DictDataInfoExample.Criteria criteria = example.createCriteria();
			criteria.andDictTypeEqualTo(info.getDictType());
			example.setOrderByClause("ID DESC");
			List<DictDataInfo> dataList = dictDataMapper.selectByExample(example);
			result.setDataList(dataList);
			return result;
		}
		return null;
	}
	
	/**在编辑页面上,需要查询当前输入的字典是否已经在数据库存在
	 * 不存在返回true
	 * 存在返回false
	 * @param id
	 * @param type
	 * @return
	 */
	public boolean checkDictTypeUnique(String id , String type) {
		DictTypeInfoExample example = new DictTypeInfoExample();
		DictTypeInfoExample.Criteria criteria = example.createCriteria();
		if(StringUtils.isNotBlank(id)) {
			criteria.andIdNotEqualTo(id);
		}
		criteria.andDictTypeEqualTo(type);
		return dictTypeMapper.countByExample(example) == 0;
	}
	
	/**批量删除部分的数据字典
	 * @param types
	 */
	@Transactional
	public void removeTypes(String[] types) {
		DictTypeInfoExample example = new DictTypeInfoExample();
		DictTypeInfoExample.Criteria criteria = example.createCriteria();
		if(types != null && types.length>0) {
			criteria.andIdIn(Arrays.asList(types));
		}
		List<DictTypeInfo> typeList = dictTypeMapper.selectByExample(example);
		
		if(typeList != null && typeList.size()>0) {
			List<String> typeStrList = new ArrayList<String>();
			for(DictTypeInfo typeInfo : typeList) {
				typeStrList.add(typeInfo.getDictType());
				//这边的cache操作,有点难看,我还没想好
				cacheManger.removeCacheKey("DICT_"+typeInfo.getDictType());
			}
			
			if(typeStrList != null && typeStrList.size()>0) {
				DictDataInfoExample dataExample = new DictDataInfoExample();
				DictDataInfoExample.Criteria dataCriteria = dataExample.createCriteria();
				dataCriteria.andDictTypeIn(typeStrList);
				dictDataMapper.deleteByExample(dataExample);
			}
			
			dictTypeMapper.deleteByExample(example);
		}
	}
	
	
	@Autowired
	private SqlSessionFactoryBean sqlSessionFactory;
	
	/**标准的mybatis批量的调用的写法
	 * @param dictTypeData
	 * @throws Exception
	 */
	@Transactional
	@DeleteCache(key = "'DICT_' + #dictTypeData.dictType")
	public void saveDictTypeData(DictTypeData dictTypeData) throws Exception{
		SqlSession session = sqlSessionFactory.getObject().openSession(ExecutorType.BATCH);
		
		DictTypeInfoMapper batchTypeMapper = session.getMapper(DictTypeInfoMapper.class);
		DictDataInfoMapper batchDataMapper = session.getMapper(DictDataInfoMapper.class);
		
		if(dictTypeData != null) {
			if(StringUtils.isNotBlank(dictTypeData.getId())) {
				//如果存在id,则代表是修改
				dictTypeData.setUpdateBy(SSOClientUtils.getInstance().findCurrentUser().getUserName());
				dictTypeData.setUpdateTime(new Date());
				batchTypeMapper.updateByPrimaryKeySelective(dictTypeData);
			}else {
				//如果不存在id,则代表新增
				dictTypeData.setCreateTime(new Date());
				dictTypeData.setCreateBy(SSOClientUtils.getInstance().findCurrentUser().getUserName());
				batchTypeMapper.insertSelective(dictTypeData);
			}
			
			//删除所有的字典项
			DictDataInfoExample dataExample = new DictDataInfoExample();
			DictDataInfoExample.Criteria dataCriteria = dataExample.createCriteria();
			dataCriteria.andDictTypeEqualTo(dictTypeData.getDictType());
			batchDataMapper.deleteByExample(dataExample);
			
			if(dictTypeData.getDataList() != null && dictTypeData.getDataList().size()>0) {
				for(DictDataInfo dataInfo : dictTypeData.getDataList()) {
					dataInfo.setDictType(dictTypeData.getDictType());
					dataInfo.setCreateTime(new Date());
					dataInfo.setCreateBy(SSOClientUtils.getInstance().findCurrentUser().getUserName());
					batchDataMapper.insertSelective(dataInfo);
				}
			}
			
			session.flushStatements();
		}
		
	}
}
